home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / plan / src / print.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  15KB  |  622 lines

  1.  
  2. /*
  3. ** Create and destroy the print popup. It is installed when the
  4. ** Print entry in the File pulldown in the main calendar window
  5. ** is used.
  6. **
  7. **    create_print_popup()
  8. **    destroy_print_popup()
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <signal.h>
  14. #include <Xm/Xm.h>
  15. #include <Xm/DialogS.h>
  16. #include <Xm/Form.h>
  17. #include <Xm/Frame.h>
  18. #include <Xm/RowColumn.h>
  19. #include <Xm/LabelP.h>
  20. #include <Xm/LabelG.h>
  21. #include <Xm/PushBP.h>
  22. #include <Xm/PushBG.h>
  23. #include <Xm/ToggleB.h>
  24. #include <Xm/TextF.h>
  25. #include <Xm/Protocols.h>
  26. #include "cal.h"
  27.  
  28. #include <fcntl.h>
  29. #include <errno.h>
  30.  
  31. #define PS_LIB "plan_cal.ps"
  32.  
  33. extern void help_callback();
  34. extern char *parse_holidays();
  35. extern struct tm *time_to_tm();
  36. extern int set_icon();
  37. extern int create_error_popup();
  38. extern BOOL lookup_entry(), lookup_next_entry();
  39.  
  40. extern int        curr_month, curr_year, curr_week;
  41. extern struct holiday    holiday[];
  42. extern struct holiday    sm_holiday[];
  43.  
  44. extern Display        *display;    /* everybody uses the same server */
  45. extern struct config    config;        /* global configuration data */
  46. extern struct list    *mainlist;    /* list of all schedule entries */
  47. extern Pixel        color[NCOLS];    /* colors: COL_* */
  48. extern char        Print_Spooler[100];/* defined in file_r.c */
  49. extern Widget        mainwindow;    /* popup menus hang off main window */
  50.  
  51. /* char *Default_Spooler = "lp -s -T ps"; */
  52. #ifdef PS_SPOOLER
  53. char *Default_Spooler = PS_SPOOLER;
  54. #else /* PS_SPOOLER */
  55. # ifdef sgi
  56. char *Default_Spooler = "lp";
  57. # else /* sgi */
  58. char *Default_Spooler = "lpr";
  59. # endif /* sgi */
  60. #endif /* PS_SPOOLER */
  61.  
  62. static BOOL        popup_created = FALSE; /* popup exists if TRUE */
  63. static Widget        print_shell;    /* popup menu shell */
  64. static Widget        spool_text;    /* Spool String Text Widget */
  65.  
  66. #define PR_YEAR        0
  67. #define PR_MONTH    1
  68. #define PR_WEEK        2
  69. #define PR_DAY        3
  70.  
  71. static int print_mode = 0;
  72.  
  73. int Print_Calendar();
  74. static int Print_Day();
  75. static void OutStr();
  76. static void mode_callback(), print_callback(), done_callback();
  77.  
  78. /*
  79. ** create a print popup as a separate application shell. When the popup
  80. ** already exists and was just popped down, pop it up and exit. This ensures
  81. ** that it comes up with the same defaults.
  82. */
  83.  
  84. void
  85. create_print_popup()
  86. {
  87.     Widget print_form, w;
  88.     Widget mode_frame, mode_form, mode_radio;
  89.     Widget spool_frame, spool_form;
  90.     Widget action_area;
  91.     Atom   closewindow;
  92.     char tmp[32];
  93.     int n;
  94.  
  95.     if(popup_created) {
  96.     XtPopup(print_shell, XtGrabNone);
  97.     return;
  98.     }
  99.  
  100.     print_shell = XtVaAppCreateShell("Print", "plan",
  101.             applicationShellWidgetClass, display,
  102.             XmNdeleteResponse,    XmDO_NOTHING,
  103.             XmNiconic,        False,
  104.             NULL);
  105.             
  106.     set_icon(print_shell, 1);
  107.  
  108.     print_form = XtCreateManagedWidget("printform", xmFormWidgetClass,
  109.             print_shell, NULL, 0);
  110.  
  111.     XtAddCallback(print_form,
  112.     XmNhelpCallback, help_callback, (XtPointer)"print");
  113.  
  114.     mode_frame = XtVaCreateManagedWidget("mode",
  115.             xmFrameWidgetClass, print_form,
  116.             XmNtopAttachment,    XmATTACH_FORM,
  117.             XmNtopOffset,    8,
  118.             XmNrightAttachment,    XmATTACH_FORM,
  119.             XmNrightOffset,    8,
  120.             XmNleftAttachment,    XmATTACH_FORM,
  121.             XmNleftOffset,    8,
  122.             NULL, 0);
  123.  
  124.     mode_form = XtCreateManagedWidget("print_mode", xmFormWidgetClass,
  125.             mode_frame, NULL, 0);
  126.  
  127.     /* Print Mode */
  128.     w = XtVaCreateManagedWidget("Print Mode:",
  129.         xmLabelWidgetClass, mode_form,
  130.         XmNtopAttachment,    XmATTACH_FORM,
  131.         XmNtopOffset,    16,
  132.         XmNleftAttachment,    XmATTACH_FORM,
  133.         XmNleftOffset,    16,
  134.         NULL);
  135.  
  136.     mode_radio = XmVaCreateSimpleRadioBox(mode_form, "radio",
  137.             0, mode_callback,
  138.             XmNtopAttachment,        XmATTACH_FORM,
  139.             XmNtopOffset,        16,
  140.             XmNleftAttachment,        XmATTACH_WIDGET,
  141.             XmNleftWidget,        w,
  142.             XmNleftOffset,        16,
  143.             XmNspacing,            4,
  144.             XmVaRADIOBUTTON,        NULL, 0, NULL, NULL,
  145.             XmVaRADIOBUTTON,        NULL, 0, NULL, NULL,
  146. #ifdef NOT_YET
  147.             XmVaRADIOBUTTON,        NULL, 0, NULL, NULL,
  148.             XmVaRADIOBUTTON,        NULL, 0, NULL, NULL,
  149. #endif
  150.             NULL);
  151.     
  152.     XtManageChild(mode_radio);
  153.  
  154.     /* Set resources for each toggleButton... */
  155. #ifdef NOT_YET
  156.     for(n = 0;n < 4;n++) {
  157. #else
  158.     for(n = 0;n < 2;n++) {
  159. #endif
  160.     sprintf(tmp, "button_%d", n);
  161.  
  162.     if((w = XtNameToWidget(mode_radio, tmp)) != NULL) {
  163.         XtVaSetValues(w, XmNselectColor, color[COL_TOGGLE], NULL);
  164.     }
  165.     }
  166.  
  167.     /* Spool String */
  168.     spool_frame = XtVaCreateManagedWidget("spool",
  169.             xmFrameWidgetClass, print_form,
  170.             XmNtopAttachment,    XmATTACH_WIDGET,
  171.             XmNtopOffset,    8,
  172.             XmNtopWidget,    mode_frame,
  173.             XmNleftAttachment,    XmATTACH_FORM,
  174.             XmNleftOffset,    8,
  175.             XmNrightAttachment,    XmATTACH_FORM,
  176.             XmNrightOffset,    8,
  177.             NULL);
  178.  
  179.     spool_form = XtCreateManagedWidget("spool_form", xmFormWidgetClass,
  180.             spool_frame, NULL, 0);
  181.  
  182.     w = XtVaCreateManagedWidget("Spooler String:",
  183.         xmLabelWidgetClass, spool_form,
  184.         XmNtopAttachment,    XmATTACH_FORM,
  185.         XmNtopOffset,    8,
  186.         XmNbottomAttachment,XmATTACH_FORM,
  187.         XmNbottomOffset,    8,
  188.         XmNleftAttachment,    XmATTACH_FORM,
  189.         XmNleftOffset,    16,
  190.         NULL);
  191.  
  192.     if (!*Print_Spooler) {
  193.     strcpy(Print_Spooler, Default_Spooler);
  194.     mainlist->modified = TRUE;
  195.     }
  196.  
  197.     spool_text = XtVaCreateManagedWidget("spooler",
  198.         xmTextFieldWidgetClass, spool_form,
  199.         XmNtopAttachment,    XmATTACH_FORM,
  200.         XmNtopOffset,    8,
  201.         XmNleftAttachment,    XmATTACH_WIDGET,
  202.         XmNleftOffset,    8,
  203.         XmNleftWidget,    w,
  204.         XmNbackground,    color[COL_TEXTBACK],
  205.         XmNvalue,        Print_Spooler,
  206.         NULL);
  207.  
  208.     /* Buttons */
  209.     action_area = XtVaCreateManagedWidget("action",
  210.         xmFormWidgetClass,        print_form,
  211.         XmNfractionBase,        10,
  212.         XmNtopAttachment,        XmATTACH_WIDGET,
  213.         XmNtopOffset,        16,
  214.         XmNtopWidget,        spool_frame,
  215.         XmNbottomAttachment,    XmATTACH_FORM,
  216.         XmNbottomOffset,        16,
  217.         XmNleftAttachment,        XmATTACH_FORM,
  218.         XmNleftOffset,        4,
  219.         XmNrightAttachment,        XmATTACH_FORM,
  220.         XmNrightOffset,        4,
  221.         NULL);
  222.  
  223.     w = XtVaCreateManagedWidget("Print",
  224.         xmPushButtonWidgetClass, action_area,
  225.         XmNtopAttachment,        XmATTACH_POSITION,
  226.         XmNtopPosition,        0,
  227.         XmNbottomAttachment,    XmATTACH_POSITION,
  228.         XmNbottomPosition,        10,
  229.         XmNleftAttachment,        XmATTACH_POSITION,
  230.         XmNleftPosition,        7,
  231.         XmNrightAttachment,        XmATTACH_POSITION,
  232.         XmNrightPosition,        9,
  233.         NULL);
  234.  
  235.     XtAddCallback(w, XmNactivateCallback, print_callback, (XtPointer)0);
  236.     XtAddCallback(w, XmNhelpCallback, help_callback, (XtPointer)"print_print");
  237.  
  238.     w = XtVaCreateManagedWidget("Cancel",
  239.         xmPushButtonWidgetClass, action_area,
  240.         XmNtopAttachment,        XmATTACH_POSITION,
  241.         XmNtopPosition,        0,
  242.         XmNbottomAttachment,    XmATTACH_POSITION,
  243.         XmNbottomPosition,        10,
  244.         XmNleftAttachment,        XmATTACH_POSITION,
  245.         XmNleftPosition,        4,
  246.         XmNrightAttachment,        XmATTACH_POSITION,
  247.         XmNrightPosition,        6,
  248.         NULL);
  249.  
  250.     XtAddCallback(w, XmNactivateCallback, done_callback, (XtPointer)0);
  251.     XtAddCallback(w, XmNhelpCallback, help_callback,
  252.                         (XtPointer)"print_cancel");
  253.  
  254.     w = XtVaCreateManagedWidget("Help",
  255.         xmPushButtonWidgetClass, action_area,
  256.         XmNtopAttachment,        XmATTACH_POSITION,
  257.         XmNtopPosition,        0,
  258.         XmNbottomAttachment,    XmATTACH_POSITION,
  259.         XmNbottomPosition,        10,
  260.         XmNleftAttachment,        XmATTACH_POSITION,
  261.         XmNleftPosition,        1,
  262.         XmNrightAttachment,        XmATTACH_POSITION,
  263.         XmNrightPosition,        3,
  264.         NULL);
  265.  
  266.     XtAddCallback(w, XmNactivateCallback, help_callback,(XtPointer)"print");
  267.     XtAddCallback(w, XmNhelpCallback,     help_callback,(XtPointer)"print");
  268.  
  269.     XtPopup(print_shell, XtGrabNone);
  270.  
  271.     closewindow = XmInternAtom(display, "WM_DELETE_WINDOW", False);
  272.  
  273.     XmAddWMProtocolCallback(print_shell, closewindow, done_callback,
  274.     (XtPointer)print_shell);
  275.  
  276.     popup_created = TRUE;
  277. }
  278.  
  279. /* Waste popup if it's been created */
  280. void
  281. destroy_print_popup()
  282. {
  283.     if(popup_created) {
  284.     XtPopdown(print_shell);
  285.     }
  286. }
  287.  
  288. /*ARGSUSED*/
  289. static void
  290. mode_callback(widget, item, data)
  291. Widget                widget;
  292. int                item;
  293. XmToggleButtonCallbackStruct    *data;
  294. {
  295.     print_mode = item;
  296. }
  297.  
  298.  
  299. /*ARGSUSED*/
  300. static void
  301. done_callback(widget, item, data)
  302. Widget                widget;
  303. int                item;
  304. XmToggleButtonCallbackStruct    *data;
  305. {
  306.     destroy_print_popup();
  307. }
  308.  
  309. static void broken_pipe_handler(sig)
  310. {
  311.     create_error_popup(mainwindow, 0,
  312.                 "Print failed, aborted with signal %d\n", sig);
  313.     signal(SIGPIPE, SIG_IGN);
  314. }
  315.  
  316. /*ARGSUSED*/
  317. static void
  318. print_callback(widget, item, data)
  319. Widget                widget;
  320. int                item;
  321. XmToggleButtonCallbackStruct    *data;
  322. {
  323.     FILE *pp;
  324.     char *Spooler = XmTextFieldGetString(spool_text);
  325.     char tmp[128];
  326.  
  327.     signal(SIGPIPE, broken_pipe_handler);
  328.  
  329.     sprintf(tmp, "exec %s", Spooler);
  330.  
  331. #if 0
  332.     fprintf(stderr, "print_callback: Mode = %d, Cmd = [%s]\n", print_mode, tmp);
  333.     fprintf(stderr, "curr_year = %d\n", curr_year);
  334.     fprintf(stderr, "curr_month = %d\n", curr_month);
  335. #endif
  336.  
  337.     /* Note any changes to spooler. */
  338.     if(strcmp(Spooler, Print_Spooler)) {
  339.     strcpy(Print_Spooler, Spooler);
  340.     mainlist->modified = TRUE;
  341.     }
  342.  
  343.     if((pp = popen(tmp, "w")) == NULL)
  344.     create_error_popup(print_shell, errno, "Cannot open pipe to \"%s\"",
  345.                                 tmp);
  346.     else
  347.     Print_Calendar(pp, print_mode, curr_month, 1, curr_year);
  348.  
  349.     destroy_print_popup();
  350.     signal(SIGPIPE, SIG_DFL);
  351. }
  352.  
  353. int
  354. Print_Calendar(Fp, Mode, Month, Day, Year)
  355. FILE *Fp;
  356. int Mode;
  357. int Month, Day, Year;
  358. {
  359.     int Pslib_Fd;
  360.     char *cp;
  361.     char tmp[512];
  362.     char PsLib[1024];
  363.     int nb;
  364.     int WeekDay, WeekNum, JulDay;
  365.     int CDay, StartDay, EndDay;
  366.     int CYear, StartYear, EndYear;
  367.     int CMonth, StartMonth, EndMonth;
  368.     char *Mode_Str;
  369.  
  370.     find_file(PsLib, PS_LIB, FALSE);
  371.     if((Pslib_Fd = open(PsLib, O_RDONLY)) == -1) {
  372.     int error = errno;
  373.     create_error_popup(print_shell, error, "Can't open %s", PsLib);
  374.     pclose(Fp);
  375.     return(-1);
  376.     }
  377.     
  378.     StartMonth = EndMonth = Month;
  379.     StartDay = 1; EndDay = 31;
  380.     StartYear  = EndYear  = Year;
  381.  
  382.     switch(Mode) {
  383.     case PR_YEAR:
  384.       Mode_Str = "Year";
  385.       Month = 0;
  386.       StartMonth = 0;
  387.       EndMonth = 11;
  388.       break;
  389.  
  390.     case PR_MONTH:
  391.       Mode_Str = "Month";
  392.       break;
  393.  
  394.     case PR_WEEK:
  395.       Mode_Str = "Week";
  396.       break;
  397.  
  398.     case PR_DAY:
  399.       Mode_Str = "Day";
  400.       StartDay = EndDay = Day;
  401.       break;
  402.     default:
  403.         pclose(Fp);
  404.         return(-2);
  405.     }
  406.  
  407.     WeekDay = -1;
  408.     date_to_time(1, Month, Year, &WeekDay, &WeekNum, &JulDay);
  409.  
  410.     if(Mode == PR_WEEK) {
  411.     StartDay = Day - WeekDay;
  412.     EndDay = StartDay + 6;
  413.     }
  414.  
  415.     fprintf(Fp, "%%!PS-Adobe\n");
  416.     fprintf(Fp, "%%\n");
  417.     fprintf(Fp, "%%%%Creator: plan\n");
  418.     fprintf(Fp, "%%%%Title: %s Calendar\n", Mode_Str);
  419.     fprintf(Fp, "%%%%EndComments\n");
  420.     fprintf(Fp, "%%\n");
  421.  
  422.     fprintf(Fp, "%% Begin of PS_LIB (%s)\n", PsLib);
  423.  
  424.     while((nb = read(Pslib_Fd, tmp, sizeof(tmp))) > 0)
  425.     fwrite(tmp, sizeof(char), nb, Fp);
  426.     close(Pslib_Fd);
  427.  
  428.     fprintf(Fp, "%% End of PS_LIB (%s)\n", PsLib);
  429.  
  430.     fflush(Fp);
  431.  
  432.     fprintf(Fp, "\n%% Plan Configuration values...\n");
  433.  
  434. #define BOOL_TO_PS(a,b) \
  435.     fprintf(Fp, "%s %s def\n", a, (b ? "true" : "false"))
  436.  
  437.     BOOL_TO_PS("/SundayFirst",   config.sunday_first);
  438.     BOOL_TO_PS("/MMDDYY",        config.mmddyy);
  439.     BOOL_TO_PS("/AMPM",          config.ampm);
  440.     BOOL_TO_PS("/Print_Julian",  config.julian);
  441.     BOOL_TO_PS("/Print_WeekNum", config.weeknum);
  442.  
  443. #undef BOOL_TO_PS
  444.  
  445.     fprintf(Fp, "\n%% Print Information\n");
  446.  
  447.     fprintf(Fp, "/Print_Mode (%s) def\n", Mode_Str);
  448.     fprintf(Fp, "/Month   %d def\n", Month + 1);
  449.     fprintf(Fp, "/Day     %d def\n", Day);
  450.     fprintf(Fp, "/Year    %d def\n", Year  + 1900);
  451.     fprintf(Fp, "/WeekDay %d def\n", WeekDay);
  452.     fprintf(Fp, "/WeekNum %d def\n", WeekNum);
  453.     fprintf(Fp, "/JulDay  %d def\n", JulDay);
  454.  
  455.     fprintf(Fp, "\n");
  456.  
  457.     fprintf(Fp, "%% Month Range: %2d thru %2d\n", StartMonth+1, EndMonth+1);
  458.     fprintf(Fp, "%% Day Range  : %2d thru %2d\n", StartDay, EndDay);
  459.     fprintf(Fp, "%% Year Range : %2d thru %2d\n", StartYear, EndYear);
  460.  
  461.     fprintf(Fp, "\nInitCal\n\n");
  462.     fprintf(Fp, "%% Data...\n\n");
  463.  
  464.     for(CYear = StartYear;CYear <= EndYear;CYear++) {
  465.      if((cp = parse_holidays(CYear, FALSE)) != NULL) {
  466.      create_error_popup(print_shell, 0, cp);
  467.      pclose(Fp);
  468.      return(-3);
  469.      }
  470.  
  471.      for(CMonth = StartMonth;CMonth <= EndMonth;CMonth++)
  472.       for(CDay = StartDay;CDay <= EndDay;CDay++)
  473.     Print_Day(Fp, CDay, CMonth, CYear);
  474.     
  475.      StartMonth = 1;
  476.      EndMonth = 12;
  477.     }
  478.  
  479.     fprintf(Fp, "\n");
  480.     fprintf(Fp, "FinishCal\n");
  481.  
  482.     pclose(Fp);
  483.     return(0);
  484. }
  485.  
  486. static int
  487. Print_Day(Fp, Day, Month, Year)
  488. FILE *Fp;
  489. int Day, Month, Year;
  490. {
  491.     int DayStart, DayEnd, WeekNum, JulDay, Found;
  492.     struct entry *Entry;
  493.     struct holiday *Hp;
  494.     struct lookup lookup;
  495.     struct tm *tm;
  496.     char *Holidays[3];
  497.     int NumHolidays;
  498.     char tmp[32];
  499.  
  500.     if(!(DayStart = date_to_time(Day, Month, Year, NULL, &JulDay, &WeekNum)))
  501.     return(-1);
  502.     
  503.     DayEnd = DayStart + 86399;
  504.  
  505.     NumHolidays = 0;
  506.  
  507.     /* Check Holidays */
  508.     if((Hp = &sm_holiday[JulDay])->string != NULL && *Hp->string)
  509.     Holidays[NumHolidays++] = Hp->string;
  510.  
  511.     if((Hp = &holiday[JulDay])->string != NULL && *Hp->string)
  512.     Holidays[NumHolidays++] = Hp->string;
  513.  
  514.     fprintf(Fp, "%d %d %d %d %d NewDay\n",
  515.         Month+1, Day, Year, WeekNum+1, JulDay+1);
  516.     
  517.     if(NumHolidays > 0) {
  518.     int i;
  519.  
  520.     fprintf(Fp, "[ ");
  521.     for(i = 0;i < NumHolidays;) {
  522.         OutStr(Fp, Holidays[i]);
  523.  
  524.         if(++i < NumHolidays)
  525.         fprintf(Fp, "\n  ");
  526.     }
  527.     fprintf(Fp, " ] PaintHolidays\n");
  528.     }
  529.  
  530.     Found = lookup_entry(&lookup, mainlist, DayStart, TRUE, FALSE);
  531.  
  532.     for(;Found;Found = lookup_next_entry(&lookup)) {
  533.     Entry = &mainlist->entry[lookup.index];
  534.  
  535.     /* Skip notes begining with '-' or '=' */
  536.     if(Entry->note && (*Entry->note == '-' || *Entry->note == '='))
  537.         continue;
  538.     
  539.     /* Only look at today's entries */
  540.     if(lookup.index >= mainlist->nentries
  541.     || lookup.trigger < DayStart
  542.     || lookup.trigger > DayEnd)
  543.         break;
  544.     
  545.     /* TODO: Add removal of past entries.. */
  546.  
  547.     /* Output Entry */
  548.     tm = time_to_tm(Entry->time);
  549.  
  550.     fprintf(Fp, "  ");
  551.  
  552.     if(config.mmddyy)
  553.         fprintf(Fp, " (%02d/%02d/%02d)\t",
  554.         tm->tm_mon+1, tm->tm_mday, tm->tm_year % 100);
  555.     else
  556.         fprintf(Fp, " (%d.%d.%02d)\t",
  557.         tm->tm_mday, tm->tm_mon+1, tm->tm_year % 100);
  558.     
  559.     if(Entry->notime)
  560.         fprintf(Fp, "()");
  561.     else {
  562.       if(config.ampm)
  563.         fprintf(Fp, "(%2d:%02d%c)\t", tm->tm_hour%12 ? tm->tm_hour%12 : 12,
  564.                        tm->tm_min,
  565.                        tm->tm_hour < 12 ? 'a' : 'p');
  566.       else
  567.         fprintf(Fp, "(%02d:%02d)\t", tm->tm_hour, tm->tm_min);
  568.     }
  569.  
  570.     OutStr(Fp, Entry->note);
  571.  
  572.     if(Entry->message && *Entry->message) {
  573.       fprintf(Fp, "\n  ");
  574.       OutStr(Fp, Entry->message);
  575.       fprintf(Fp, "\n PaintEntry\n");
  576.     } else
  577.       fprintf(Fp, "\t() PaintEntry\n");
  578.  
  579.     fflush(Fp);
  580.     }
  581.  
  582.     fflush(Fp);
  583.  
  584.     return(0);
  585. }
  586.  
  587. /* Output a string in a manner compatible with PostScript.. */
  588. static void
  589. OutStr(Fp, Str)
  590. FILE *Fp;
  591. char *Str;
  592. {
  593.     /* Not perfect but It'll work for now... */
  594.     putc('(', Fp);
  595.  
  596.     for(;Str && *Str;Str++)
  597.     switch(*Str) {
  598.         case '\n':
  599.           /* String trailing New Lines */
  600.           if(!*(Str+1))
  601.           break;
  602.  
  603.           /* Replace Newlines we spaces... */
  604.           /* In the "PostScript" we output an escaped newline */
  605.           /* to improve readability */
  606.           putc(' ', Fp);
  607.  
  608.         case '\\': case '(': case ')':
  609.           fprintf(Fp, "\\%c", *Str);
  610.           break;
  611.         
  612.         case '\f': fprintf(Fp, "\\f"); break;
  613.         case '\r': fprintf(Fp, "\\r"); break;
  614.  
  615.         default:
  616.         putc(*Str, Fp);
  617.         break;
  618.     }
  619.  
  620.     putc(')', Fp);
  621. }
  622.